﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Drawing;
using System.Runtime.InteropServices;
using System.Windows.Forms;
using XFControls.Utils;
using XFControls.XFPanels.XFPanelItems;
using System.Collections;
using System.IO;

#pragma warning disable 1591
// ReSharper disable InconsistentNaming

namespace XFControls.XFPanels
{
    public partial class XFPanelImage : XFPanelBase
    {
        public EventHandler PreviousImageClick;
        public EventHandler ExitClick;
        public EventHandler CommentsClick;
        public EventHandler NextImageClick;

        public bool PanelReceiveSwipe;
        public string LoadingString;
        public int CommentCount = -1;

        private Timer _clickTimer;
        private string _file;
        private Rectangle _recImg;
        private Rectangle _recControls;
        private bool _zoomed;
        private bool _displayControls;
        private Bitmap _buffer;

        public XFPanelImage()
        {
            BackColor = Color.Black;
            InitializeComponent();
            Width = Screen.PrimaryScreen.Bounds.Width;
            Height = Screen.PrimaryScreen.Bounds.Height;
            _clickTimer = new Timer();
            _clickTimer.Interval = 400;
            _clickTimer.Tick += ShowControls;

            var drawer = new XFItemBase();
            _recControls = drawer.GetImageRec("image_controls");
        }

        public void SetImage(string file)
        {
            _file = file;

            var size = ImageHeader.GetDimensions(_file);
            _recImg = new Rectangle(0, 0, size.Width, size.Height);
            Damage();
        }

        public void SetImage(string file, byte[] array)
        {
            _file = file;

            var size = ImageHeader.GetDimensions(array);

            if (size.Height == size.Width && size.Height == 0)
                return;

            _recImg = new Rectangle(0, 0, size.Width, size.Height);
            Damage();
        }

        public override void DoSwipe(Point mouseDown, Point mouseUp)
        {
            if ((mouseUp.X - mouseDown.X) > (Screen.PrimaryScreen.WorkingArea.Width / 3))
            {
                PreviousImage();
            }
            else if ((mouseDown.X - mouseUp.X) > (Screen.PrimaryScreen.WorkingArea.Width / 3))
            {
                NextImage();
            }
        }

        public override void PanelPaint(Graphics g)
        {
            var rec = new Rectangle(0, 0, Parent.Width, Parent.Height);
            g.Clear(BackColor);

            if (!string.IsNullOrEmpty(_file))
            {
                if (!DrawImageFile(g, rec))
                {
                    using (var f = new Font(FontFamily.GenericSansSerif, 8, FontStyle.Regular))
                    {
                        const string error = "There was an unknown error.";
                        var size = f.MeasureString(error, _recImg);

                        rec.Y = (rec.Height >> 1) - (size.Height >> 1);

                        g.DrawString(error, rec, XFItemTextAlign.Center, f, Color.White);
                    }
                }
            }
            else
            {
                using (var f = new Font(FontFamily.GenericSansSerif, 8, FontStyle.Regular))
                {
                    var size = f.MeasureString(LoadingString, _recImg);

                    rec.Y = (rec.Height >> 1) - (size.Height >> 1);

                    g.DrawString(LoadingString, rec, XFItemTextAlign.Center, f, Color.White);
                }
            }

            if (!_displayControls) return;

            using (var drawer = new XFItemBase())
                drawer.DrawUI("image_controls", g, _recControls);

            if (CommentCount < 0) return;

            using (var f = new Font(FontFamily.GenericSansSerif, 9, FontStyle.Regular))
            {
                int quarter = Parent.Width >> 2;
                int twoThirdsQuarter = (int)(quarter * (1f / 3f));
                rec = new Rectangle(quarter * 2 + twoThirdsQuarter, (int)(_recControls.Height * (2f / 3f)), quarter, Parent.Width);
                g.DrawString(CommentCount.ToString(), rec, XFItemTextAlign.Center, f, Color.White);
            }

        }

        private bool DrawImageFile(Graphics g, Rectangle rec)
        {
            if (_buffer != null)
            {
                g.DrawImage(_buffer, 0, 0);
                return true;
            }

            if (_recImg.IsEmpty)
            {
                var s = ImageHeader.GetDimensions(_file);
                _recImg = new Rectangle(0, 0, s.Width, s.Height);
            }

            Rectangle recImg = _recImg;
            bool flip = false;

            if (!_zoomed)
            {
                if (_recImg.Width > _recImg.Height)
                {
                    _recImg = new Rectangle(0, 0, _recImg.Height, _recImg.Width);
                    flip = true;
                }

                recImg = rec.ScaleToFitInside(_recImg, true);

                if (flip)
                    recImg = new Rectangle(recImg.X, recImg.Y, recImg.Height, recImg.Width);
            }
            _buffer = XFBitmapFactory.GetBitmap(rec.Width, rec.Height);

            try
            {
                using (var gr = Graphics.FromImage(_buffer))
                using (var b = XFGraphics.GetBitmap(_file, new Rectangle(0, 0, recImg.Width, recImg.Height)))
                {
                    gr.Clear(BackColor);

                    if (b != null)
                    {
                        if (!flip)
                            gr.DrawImage(b, recImg.X, recImg.Y);
                        else
                        {
                            using (var b2 = XFGraphics.GetBitmap(_file, new Rectangle(0, 0, recImg.Height, recImg.Width)))
                            {
                                XFGraphics.RotateImage(90, b, b2);
                                gr.DrawImage(b2, recImg.X, recImg.Y);
                            }
                        }
                    }
                    else
                        Damage();
                }
                g.DrawImage(_buffer, 0, 0);

                return true;
            }
            catch (OutOfMemoryException)
            {
                return false;
            }
        }

        protected override void OnMouseDown(MouseEventArgs e)
        {
            base.OnMouseDown(e);

            switch (_curState)
            {
                case States.Click:
                    break;
                case States.Idle:
                    break;
                default:
                    break;
            }
        }

        protected override void OnMouseUp(MouseEventArgs e)
        {
            switch (_curState)
            {
                case States.Scroll:
                case States.Click:
                    if (_displayControls && _recControls.Contains(e.X, e.Y))
                    {
                        ControlClick(e.X);
                        break;
                    }
                    _displayControls = !_displayControls;
                    break;
            }

            base.OnMouseUp(e);
        }

        private void ControlClick(int x)
        {
            int forth = _recControls.Width >> 2;

            switch (x / forth)
            {
                case 0:
                    PreviousImage();
                    break;

                case 1:
                    Exit();
                    break;

                case 2:
                    Comments();
                    break;

                case 3:
                    NextImage();
                    break;
            }
        }

        private void NextImage()
        {
            if (NextImageClick != null)
                NextImageClick(this, new EventArgs());
        }

        private void Comments()
        {
            if (CommentsClick != null)
                CommentsClick(this, new EventArgs());
        }

        private void Exit()
        {
            if (ExitClick != null)
                ExitClick(this, new EventArgs());
        }

        private void PreviousImage()
        {
            if (PreviousImageClick != null)
                PreviousImageClick(this, new EventArgs());
        }

        protected override void OnMouseMove(MouseEventArgs e)
        {
            base.OnMouseMove(e);

            switch (_curState)
            {
                case States.Scroll:
                    break;
                case States.Swipe:
                    break;
            }
        }

        void ShowControls(object sender, EventArgs e)
        {
            _clickTimer.Enabled = false;
        }

        protected override void Dispose()
        {
            base.Dispose();
            _clickTimer.Dispose();
            _clickTimer = null;

            PreviousImageClick = null;
            ExitClick = null;
            CommentsClick = null;
            NextImageClick = null;

            if (_buffer != null)
                _buffer.Dispose();
            _buffer = null;
        }
    }
}

// ReSharper restore InconsistentNaming
#pragma warning restore 1591
